package com.dhcc.bpm.modules.auth.controller;

import com.dhcc.bpm.common.annotation.Log;
import com.dhcc.bpm.common.config.AppTokenConfig;
import com.dhcc.bpm.common.enums.BusinessType;
import com.dhcc.bpm.common.redisMessage.RedisMessageSender;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.annotation.ApiLog;
import org.springblade.core.tool.api.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * @ClassName TokenController
 * @Description token服务接口
 * @Author sjm
 * @Date 2020/2/21 0021 15:16
 * @Version V1.0
 * @Copyright: 2020 东华软件 . All rights reserved.
 **/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/token")
@Api(value = "应用/渠道token信息", tags = "应用/渠道token信息接口")
public class TokenController {

    private TokenStore tokenStore;
    private RestTemplate restTemplate;
    private AppTokenConfig appTokenConfig;
    @Autowired
    private RedisMessageSender redisMessageSender;

    /**
     * @param clientId
     * @return java.util.Collection<org.springframework.security.oauth2.common.OAuth2AccessToken>
     * @Description 查询token
     * @Author xiafayu
     * @Date 2020/2/24 17:35
     **/
    @ApiLog("查询token")
    @GetMapping("/findTokens")
    @Log(title = "查询token", businessType = BusinessType.SELECT)
    public Collection<OAuth2AccessToken> findTokensByClientId(String clientId) {
        Collection<OAuth2AccessToken> findTokensByClientId = tokenStore.findTokensByClientId(clientId);
        return findTokensByClientId.stream().filter(p -> readAccessToken(p.getValue()) != null)
                .collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(OAuth2AccessToken::getValue))), ArrayList::new));
    }

    /**
     * @param clientId
     * @param userName
     * @return java.util.Collection<org.springframework.security.oauth2.common.OAuth2AccessToken>
     * @Description 查询
     * @Author xiafayu
     * @Date 2020/2/24 17:36
     **/
    @GetMapping("/findTokens/user/")
    public Collection<OAuth2AccessToken> findTokensByClientId(String clientId, String userName) {
        return tokenStore.findTokensByClientIdAndUserName(clientId,
                userName);
    }

    /**
     * @param token
     * @return org.springframework.security.oauth2.common.OAuth2AccessToken
     * @Description 查询
     * @Author xiafayu
     * @Date 2020/2/24 17:36
     **/
    @GetMapping("/readToken")
    public OAuth2AccessToken readAccessToken(String token) {
        return tokenStore.readAccessToken(token);
    }

    /**
     * @param token
     * @return org.springframework.security.oauth2.provider.OAuth2Authentication
     * @Description 查询
     * @Author xiafayu
     * @Date 2020/2/24 17:36
     **/
    @GetMapping("/readAuth")
    public OAuth2Authentication readAuthentication(String token) {
        return tokenStore.readAuthentication(token);
    }

    /**
     * @param token
     * @return org.springframework.security.oauth2.common.OAuth2RefreshToken
     * @Description 查询
     * @Author xiafayu
     * @Date 2020/2/24 17:36
     **/
    @GetMapping("/readRefreshToken")
    public OAuth2RefreshToken readRefreshToken(String token) {
        return tokenStore.readRefreshToken(token);
    }

    /**
     * @param id
     * @return org.springblade.core.tool.api.R
     * @Description 删除
     * @Author xiafayu
     * @Date 2020/2/24 17:36
     **/
    @ApiLog("删除token")
    @PostMapping("/removeToken")
    @Log(title = "删除token", businessType = BusinessType.DELETE)
    public R<Boolean> removeAccessToken(String id) {
        redisMessageSender.sendMessageToChannel("TOKEN", "del:" + id);
        OAuth2AccessToken readAccessToken = tokenStore.readAccessToken(id);
        if (readAccessToken != null) {
            tokenStore.removeAccessToken(readAccessToken);
        }
        return R.status(true);
    }

    /**
     * @param token
     * @return void
     * @Description 删除
     * @Author xiafayu
     * @Date 2020/2/24 17:37
     **/
    @GetMapping("/removeRefreshToken")
    public void removeRefreshToken(String token) {
        OAuth2RefreshToken readRefreshToken = tokenStore.readRefreshToken(token);
        tokenStore.removeRefreshToken(readRefreshToken);
    }

    /**
     * @param token
     * @return void
     * @Description 删除
     * @Author xiafayu
     * @Date 2020/2/24 17:37
     **/
    @GetMapping("/removeTokenByRefreshToken")
    public void removeTokenByRefreshToken(String token) {
        OAuth2RefreshToken readRefreshToken = tokenStore.readRefreshToken(token);
        tokenStore.removeAccessTokenUsingRefreshToken(readRefreshToken);
    }

    /**
     * @param appId
     * @param appSecret
     * @param refreshToken
     * @return org.springblade.core.tool.api.R
     * @Description 刷新
     * @Author xiafayu
     * @Date 2020/2/24 17:37
     **/
    @ApiLog("刷新token")
    @PostMapping("/refreshToken")
    @Log(title = "刷新token", businessType = BusinessType.DELETE)
    public R<Boolean> refreshToken(String appId, String appSecret, String refreshToken) {
        String url = "http://" + appTokenConfig.getTokenUrl() + "/auth/oauth/token?grant_type=refresh_token&refresh_token=" + refreshToken
                + "&client_id=" + appId
                + "&client_secret=" + appSecret;
        restTemplate.getForEntity(url, String.class);
        return R.status(true);
    }

    /**
     * @param appId
     * @param appSecret
     * @return org.springblade.core.tool.api.R
     * @Description 刷新
     * @Author wangjinghan
     * @Date 2022年11月9日09:59:11
     **/
    @ApiLog("重新生成token")
    @GetMapping("/generateToken")
    @Log(title = "重新生成token", businessType = BusinessType.DELETE)
    public R<Boolean> generateToken(String appId, String appSecret) {
        String url = "http://" + appTokenConfig.getTokenUrl() + "/auth/oauth/token?grant_type=client_credentials"
                + "&client_id=" + appId
                + "&client_secret=" + appSecret;
        try {
            restTemplate.getForEntity(url, String.class);
        } catch (Exception e) {
            log.error("生成token异常：", e);
            return R.fail("生成token失败！");
        }
        return R.status(true);
    }

}
